//
// File:	TestEntities.cpp
// Author:	Thomas TISSOT-DUPONT
// Login:	<thomas.tissotdupont@free.fr>
//
// Created:	25/04/2010 at 00:34:21
// Purpose:	
//
#include "TestEntities.hpp"
#include "Trace.hpp"

//------------------------------------------------------------------
// EnvAmbientSound
//------------------------------------------------------------------
void EnvAmbientSound::OnCreate()
{
	SetRenderGroup(RENDERGROUP_NODRAW);
	ISound *pSound = EmitSound(m_soundPath, true, true, m_bSpatialization);
	CONNECT_METHOD_0(pSound, OnStopped, this, &IEntity::Remove);
	BaseEntity::OnCreate();
}

void EnvAmbientSound::OnCreateDataMap()
{
	DECLARE_DATAMAP_FIELD("sound",				m_soundPath,			std::string());
	DECLARE_DATAMAP_FIELD("spatialization",		m_bSpatialization,		true);
	BaseEntity::OnCreateDataMap();
}

//------------------------------------------------------------------
// FXTemporary
//------------------------------------------------------------------
void FXTemporary::OnCreate()
{
	SetRenderGroup(RENDERGROUP_EFFECTS);
	BaseEntity::OnCreate();
}

BaseEntity *FXTemporary::LoadEffect(const std::string &fileName, const std::string &animName)
{
	FXTemporary *pEffect = dynamic_cast<FXTemporary *>(BaseEntity::CreateEntityByName("fx_temporary"));
	if (pEffect == NULL)
		return NULL;
	pEffect->LoadFromFile(fileName);
	pEffect->GetAnimating()->PlayAnimation(animName);
	CONNECT_METHOD_0(pEffect->GetAnimating()->GetCurrentAnimation(), OnAnimationFinished, pEffect, &FXTemporary::Remove);
	return pEffect;
}

//------------------------------------------------------------------
// Missile
//------------------------------------------------------------------
void Missile::OnCreate()
{
	SetRenderGroup(RENDERGROUP_EFFECTS);
	LoadFromFile("data/sprites/missile/missile.spr");
	GetAnimating()->PlayAnimation("idle");

	EmitSound("data/sound/missile_fly.snd", true, true);
	BaseEntity::OnCreate();
}

void Missile::Update()
{
	if (!GlobalVariables::DisplayManager::Get().GetView()->IsRectInside(GetCenterX(), GetCenterY(), GetWidth(), GetHeight()))
	{
		Remove();
		EmitSound("data/sound/missile_explode.snd");
	}
	BaseEntity::Update();
}

BaseEntity *Missile::CreateMissile(float flCenterX, float flCenterY, float flVelocityX /* = 0.0f */, float flVelocityY /* = 0.0f */)
{
	BaseEntity *pMissile = BaseEntity::CreateEntityByName("missile");
	if (pMissile != NULL)
	{
		pMissile->SetCenterX(flCenterX);
		pMissile->SetCenterY(flCenterY);
		pMissile->SetVelocityX(flVelocityX);
		pMissile->SetVelocityY(flVelocityY);
	}
	return pMissile;
}

//------------------------------------------------------------------
// BigPink
//------------------------------------------------------------------
void BigPink::OnCreate()
{
	SetRenderGroup(RENDERGROUP_CHARACTERS);
	LoadFromFile("data/sprites/mob/big-pink.spr");
	CONNECT_METHOD_0(GetAnimating()->GetAnimationByName("open"),  OnAnimationFinished, this, &BigPink::Close);
	CONNECT_METHOD_0(GetAnimating()->GetAnimationByName("close"), OnAnimationFinished, this, &BigPink::Open);
	Open();
	BaseEntity::OnCreate();
}

void BigPink::Update()
{
	if (!GlobalVariables::DisplayManager::Get().GetView()->IsRectInside(GetCenterX(), GetCenterY(), GetWidth(), GetHeight()))
	{
		Remove();
	}
	BaseEntity::Update();
}

void BigPink::Close()
{
	Missile *pMissile = dynamic_cast<Missile *>(Missile::CreateMissile(GetCenterX(), GetY()));
	if (pMissile != NULL)
	{
		CONNECT_METHOD_1(pMissile, OnUpdated, this, &BigPink::Missile_Update);
		CONNECT_METHOD_1(pMissile, OnRemoved, this, &BigPink::Missile_Remove);
		EmitSound("data/sound/missile_shoot.snd");
	}
	GetAnimating()->PlayAnimation("close");
}

void BigPink::Open()
{
	GetAnimating()->PlayAnimation("open");
}

void BigPink::Missile_Update(BaseEntity *pMissile)
{
	pMissile->SetVelocityY(-100.0f);
	pMissile->SetVelocityX(100.0f * cosf(0.0125f * (pMissile->GetY() - GetY())));
}

void BigPink::Missile_Remove(BaseEntity *pMissile)
{
	BaseEntity *pExplosion = FXTemporary::LoadEffect("data/sprites/effects/explosion/explosion.spr", "explode");
	if (pExplosion != NULL)
	{
		pExplosion->SetCenterX(pMissile->GetCenterX());
		pExplosion->SetCenterY(pMissile->GetCenterY());
	}
}

//------------------------------------------------------------------
// BasePlayer
//------------------------------------------------------------------
const BasePlayer::Color &BasePlayer::GetPlayerColor(ColorName colorName)
{
	static std::map<ColorName, Color> colorsMap;
	if (colorsMap.empty())
	{
		colorsMap[Invalid]	= Color(  0,   0,   0,  0);
		colorsMap[Blue]		= Color( 64,  64, 255, 255);
		colorsMap[Cyan]		= Color( 64, 224, 255, 255);
		colorsMap[Purple]	= Color(255,  32, 224, 255);
		colorsMap[Green]	= Color(112, 255,  44, 255);
		colorsMap[Red]		= Color(255,  44,  16, 255);
	}
	return colorsMap[colorName];
}

const std::string &BasePlayer::GetPlayerSprite(ColorName colorName)
{
	static std::map<ColorName, std::string> spritesMap;
	if (spritesMap.empty())
	{
		spritesMap[Invalid]	= "(null)";
		spritesMap[Blue]	= "data/sprites/player/blue.spr";
		spritesMap[Cyan]	= "data/sprites/player/cyan.spr";
		spritesMap[Purple]	= "data/sprites/player/purple.spr";
		spritesMap[Green]	= "data/sprites/player/green.spr";
		spritesMap[Red]		= "data/sprites/player/red.spr";
	}
	return spritesMap[colorName];
}

void BasePlayer::SetColorName(ColorName colorName)
{
	//Stop any current playing animation
	if (GetAnimating() != NULL)
		GetAnimating()->StopAnimation();

	//Get my color
	m_color = GetPlayerColor(colorName);

	//Load my color-sprite
	LoadFromFile(GetPlayerSprite(colorName));

	//Remove my old color-arrow
	if (m_pArrow != NULL)
		m_pArrow->Remove();

	//Create my new color-arrow
	m_pArrow = FXTemporary::LoadEffect("data/sprites/player/arrow.spr", "idle");
	if (m_pArrow != NULL)
	{
		m_pArrow->FollowEntity(this);
		m_pArrow->SetFollowOffsetCenterX(GetWidth() * 0.5f);
		m_pArrow->SetFollowOffsetCenterY(-GetHeight());
		m_pArrow->GetAnimating()->SetRenderColor(m_color.r, m_color.g, m_color.b, m_color.a);
	}
}

void BasePlayer::OnCreate()
{
	m_pArrow = NULL;
	m_color = Invalid;
	m_flNextShootTime = 0.0f;

	SetRenderGroup(RENDERGROUP_CHARACTERS);
	SetColorName(Invalid);
	BaseEntity::OnCreate();
}

void BasePlayer::OnDestroy()
{
	m_pArrow->Remove();
	BaseEntity::OnDestroy();
}

void BasePlayer::Update()
{
	if (GlobalVariables::InputManager::Get().HasInput("shoot") && m_flNextShootTime <= GlobalVariables::Global::Get().GetCurTime())
	{
		//Railgun Trail Effect
		BaseEntity *pTrailEffect = FXTemporary::LoadEffect("data/sprites/effects/trail.spr", "idle");
		if (pTrailEffect != NULL)
		{
			pTrailEffect->SetX(GetX() + GetWidth());
			pTrailEffect->SetCenterY(GetCenterY());
			pTrailEffect->GetAnimating()->SetRenderColor(m_color.r, m_color.g, m_color.b, m_color.a);
		}

		//MuzzleFlash
		BaseEntity *pMuzzleFlashEffect = FXTemporary::LoadEffect("data/sprites/effects/shoot.spr", "idle");
		if (pMuzzleFlashEffect != NULL)
		{
			pMuzzleFlashEffect->FollowEntity(this);
			pMuzzleFlashEffect->SetFollowOffsetX(GetWidth());
			pMuzzleFlashEffect->SetFollowOffsetCenterY(GetHeight() * 0.5f);
		}

		//Railgun Sound
		EmitSound("data/sound/railgun_shoot.snd");

		//Next Shoot Time
		m_flNextShootTime = GlobalVariables::Global::Get().GetCurTime() + 1.75f;
	}

	if (GlobalVariables::InputManager::Get().HasInput("move_up"))
		GetAnimating()->PlayAnimation("up");
	else if (GlobalVariables::InputManager::Get().HasInput("move_down"))
		GetAnimating()->PlayAnimation("down");
	else
		GetAnimating()->PlayAnimation("idle");

	float flSpeed = 200.0f;
	std::map<std::string, sf::Vector2f> velocityMap;
	velocityMap["move_up"] = sf::Vector2f(0, -flSpeed);
	velocityMap["move_down"] = sf::Vector2f(0, flSpeed);
	velocityMap["move_left"] = sf::Vector2f(-flSpeed, 0);
	velocityMap["move_right"] = sf::Vector2f(flSpeed, 0);
	std::map<std::string, sf::Vector2f>::iterator it = velocityMap.begin();
	std::map<std::string, sf::Vector2f>::iterator ite = velocityMap.end();

	SetVelocityX(0);
	SetVelocityY(0);
	for (; it != ite; ++it)
	{
		if (GlobalVariables::InputManager::Get().HasInput(it->first))
		{
			SetVelocityX(GetVelocityX() + it->second.x);
			SetVelocityY(GetVelocityY() + it->second.y);
		}
	}
	BaseEntity::Update();
}

//------------------------------------------------------------------
// ScrollEntity
//------------------------------------------------------------------
void ScrollEntity::Update()
{
	GlobalVariables::DisplayManager::Get().GetView()->SetViewCenterX(GetCenterX());
	BaseEntity::Update();
}

//------------------------------------------------------------------
// SpawnPoint
//------------------------------------------------------------------
void SpawnPoint::Update()
{
	BaseEntity::Update();
}
